package com.qf.order.service.impl;

import com.qf.order.domain.dto.OrderAnalysisDTO;
import com.qf.order.domain.dto.OrderDistributionDTO;
import com.qf.order.domain.dto.OrderStatsDTO;
import com.qf.order.domain.dto.OrderTrendDTO;
import com.qf.order.mapper.OrderAnalysisMapper;
import com.qf.order.service.OrderAnalysisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单分析服务实现类
 */
@Service
public class OrderAnalysisServiceImpl implements OrderAnalysisService {

    @Autowired
    private OrderAnalysisMapper orderAnalysisMapper;

    /**
     * 获取订单统计数据
     */
    @Override
    public OrderStatsDTO getOrderStats(OrderAnalysisDTO params) {
        // 1. 处理时间参数（设置默认近30天）
        handleTimeParams(params);

        // 2. 查询当前周期数据（非空校验，避免空对象后续操作）
        OrderStatsDTO currentStats = orderAnalysisMapper.selectOrderStats(params);
        if (currentStats == null) {
            currentStats = new OrderStatsDTO();
            currentStats.setTotalOrders(0);
            currentStats.setTotalAmount(0.0);
            currentStats.setCompletedOrders(0);
            currentStats.setAvgProcessTime(0.0);
        }

        // 3. 查询上一周期数据（用于计算趋势）
        OrderAnalysisDTO lastPeriodParams = copyParams(params);
        calculateLastPeriod(lastPeriodParams);
        OrderStatsDTO lastStats = orderAnalysisMapper.selectOrderStats(lastPeriodParams);

        // 4. 计算趋势（环比）
        calculateTrend(currentStats, lastStats);

        return currentStats;
    }

    /**
     * 获取订单趋势数据
     */
    @Override
    public OrderTrendDTO getOrderTrend(OrderAnalysisDTO params) {
        // 初始化趋势DTO，避免返回null
        OrderTrendDTO trendDTO = new OrderTrendDTO();
        trendDTO.setCategories(new ArrayList<>());
        trendDTO.setOrderCounts(new ArrayList<>());
        trendDTO.setOrderAmounts(new ArrayList<>());

        // 处理时间参数（默认按日查询）
        handleTimeParams(params);

        // 根据时间粒度查询并转换数据（全分支非空校验）
        if ("week".equals(params.getTimeRange())) {
            List<Map<String, Object>> weekData = orderAnalysisMapper.selectWeekTrend(params);
            if (weekData != null && !weekData.isEmpty()) {
                trendDTO = convertToTrendDTO(weekData, "week");
            }
        } else if ("month".equals(params.getTimeRange())) {
            List<Map<String, Object>> monthData = orderAnalysisMapper.selectMonthTrend(params);
            if (monthData != null && !monthData.isEmpty()) {
                trendDTO = convertToTrendDTO(monthData, "month");
            }
        } else {
            List<Map<String, Object>> dayData = orderAnalysisMapper.selectDayTrend(params);
            if (dayData != null && !dayData.isEmpty()) {
                trendDTO = convertToTrendDTO(dayData, "day");
            }
        }

        return trendDTO;
    }

    /**
     * 获取订单分布数据
     */
    @Override
    public OrderDistributionDTO getOrderDistribution(OrderAnalysisDTO params) {
        // 处理时间参数
        handleTimeParams(params);

        // 初始化分布DTO，避免返回null
        OrderDistributionDTO distributionDTO = new OrderDistributionDTO();
        distributionDTO.setStatusDistribution(new HashMap<>());
        distributionDTO.setTransportDistribution(new HashMap<>());
        distributionDTO.setRegionDistribution(new HashMap<>());
        distributionDTO.setCustomerDistribution(new HashMap<>());

        // 1. 状态分布（非空校验，避免空集合循环）
        List<Map<String, Object>> statusList = orderAnalysisMapper.selectStatusDistribution(params);
        if (statusList != null && !statusList.isEmpty()) {
            distributionDTO.setStatusDistribution(convertToMap(statusList, "order_status", "count"));
        }

        // 2. 运输类型分布
        List<Map<String, Object>> transportList = orderAnalysisMapper.selectTransportDistribution(params);
        if (transportList != null && !transportList.isEmpty()) {
            distributionDTO.setTransportDistribution(convertToMap(transportList, "transport_type", "count"));
        }

        // 3. 区域分布（按始发地）
        List<Map<String, Object>> regionList = orderAnalysisMapper.selectRegionDistribution(params);
        if (regionList != null && !regionList.isEmpty()) {
            distributionDTO.setRegionDistribution(convertToMap(regionList, "origin", "count"));
        }

        // 4. 客户分布
        List<Map<String, Object>> customerList = orderAnalysisMapper.selectCustomerDistribution(params);
        if (customerList != null && !customerList.isEmpty()) {
            distributionDTO.setCustomerDistribution(convertToMap(customerList, "customer_name", "count"));
        }

        return distributionDTO;
    }

    // ------------------------------ 工具方法 ------------------------------

    /**
     * 处理时间参数（设置默认值，避免null）
     */
    private void handleTimeParams(OrderAnalysisDTO params) {
        if (params == null) {
            throw new IllegalArgumentException("参数对象OrderAnalysisDTO不能为null");
        }
        // 时间范围默认近30天
        if (ObjectUtils.isEmpty(params.getStartDate()) || ObjectUtils.isEmpty(params.getEndDate())) {
            params.setEndDate(LocalDate.now());
            params.setStartDate(LocalDate.now().minusDays(30));
        }
        // 时间粒度默认按日
        if (ObjectUtils.isEmpty(params.getTimeRange())) {
            params.setTimeRange("day");
        }
    }

    /**
     * 计算上一周期时间范围（基于当前周期长度）
     */
    private void calculateLastPeriod(OrderAnalysisDTO params) {
        if (params == null || params.getStartDate() == null || params.getEndDate() == null) {
            return;
        }
        LocalDate start = params.getStartDate();
        LocalDate end = params.getEndDate();
        // 计算当前周期天数
        long days = end.toEpochDay() - start.toEpochDay();
        // 上一周期：当前周期开始前1天 到 当前周期开始前(days+1)天
        params.setEndDate(start.minusDays(1));
        params.setStartDate(start.minusDays(days + 1));
    }

    /**
     * 复制参数对象（深拷贝关键字段，避免原对象修改影响）
     */
    private OrderAnalysisDTO copyParams(OrderAnalysisDTO params) {
        if (params == null) {
            return new OrderAnalysisDTO();
        }
        OrderAnalysisDTO copy = new OrderAnalysisDTO();
        copy.setStartDate(params.getStartDate());
        copy.setEndDate(params.getEndDate());
        copy.setOrderStatus(params.getOrderStatus());
        copy.setTransportType(params.getTransportType());
        copy.setTimeRange(params.getTimeRange());
        return copy;
    }

    /**
     * 计算趋势（环比增长率，处理null和0值）
     */
    private void calculateTrend(OrderStatsDTO current, OrderStatsDTO last) {
        if (current == null) {
            return;
        }
        // 上一周期数据为null时，趋势默认为0
        if (last == null) {
            current.setTotalOrdersTrend(0.0);
            current.setTotalAmountTrend(0.0);
            current.setCompletedOrdersTrend(0.0);
            current.setAvgProcessTimeTrend(0.0);
            return;
        }

        // 总订单数趋势
        current.setTotalOrdersTrend(calculateRate(current.getTotalOrders(), last.getTotalOrders()));
        // 总金额趋势
        current.setTotalAmountTrend(calculateRate(current.getTotalAmount(), last.getTotalAmount()));
        // 已完成订单趋势
        current.setCompletedOrdersTrend(calculateRate(current.getCompletedOrders(), last.getCompletedOrders()));
        // 平均处理时间趋势（反向：上周期时间 / 当前周期时间 - 1，时间越少越好）
        current.setAvgProcessTimeTrend(calculateRate(last.getAvgProcessTime(), current.getAvgProcessTime()));
    }

    /**
     * 计算增长率：(当前值 - 上周期值) / 上周期值 * 100%（处理null和除数为0）
     */
    private Double calculateRate(Number current, Number last) {
        if (current == null || last == null) {
            return 0.0;
        }
        double lastValue = last.doubleValue();
        double currentValue = current.doubleValue();
        // 上周期值为0时，增长率默认为0（避免除以0）
        if (lastValue == 0) {
            return 0.0;
        }
        // 保留1位小数
        return Math.round((currentValue - lastValue) / lastValue * 100 * 10) / 10.0;
    }

    /**
     * 转换为趋势DTO（核心修复：全字段非空校验 + 默认值处理）
     */
    private OrderTrendDTO convertToTrendDTO(List<Map<String, Object>> dataList, String type) {
        // 初始化DTO及集合，避免null
        OrderTrendDTO trendDTO = new OrderTrendDTO();
        trendDTO.setCategories(new ArrayList<>());
        trendDTO.setOrderCounts(new ArrayList<>());
        trendDTO.setOrderAmounts(new ArrayList<>());

        if (dataList == null || dataList.isEmpty() || type == null) {
            return trendDTO;
        }

        // 循环处理每一条数据，全字段非空校验
        for (Map<String, Object> data : dataList) {
            if (data == null) {
                continue; // 跳过空Map，避免后续操作异常
            }

            // 1. 时间分类（如day/week/month）：null时用空字符串占位
            Object typeValue = data.get(type);
            trendDTO.getCategories().add(typeValue != null ? typeValue.toString() : "未知时间");

            // 2. 订单数：null或非数字时默认为0
            Object countObj = data.get("count");
            int count = 0;
            if (countObj instanceof Number) {
                count = ((Number) countObj).intValue();
            }
            trendDTO.getOrderCounts().add(count);

            // 3. 订单金额：null或非数字时默认为0.0，转换为万元单位（保留2位小数）
            Object amountObj = data.get("amount");
            double amount = 0.0;
            if (amountObj instanceof Number) {
                amount = ((Number) amountObj).doubleValue() / 10000;
                amount = Math.round(amount * 100) / 100.0; // 保留2位小数
            }
            trendDTO.getOrderAmounts().add(amount);
        }

        return trendDTO;
    }

    /**
     * 转换为Map（非空校验，避免空键/空值）
     */
    private Map<String, Integer> convertToMap(List<Map<String, Object>> list, String keyName, String valueName) {
        Map<String, Integer> resultMap = new HashMap<>();
        if (list == null || list.isEmpty() || keyName == null || valueName == null) {
            return resultMap;
        }

        for (Map<String, Object> item : list) {
            if (item == null) {
                continue; // 跳过空Map
            }

            // 键：null时用"未知"占位
            Object keyObj = item.get(keyName);
            String key = keyObj != null ? keyObj.toString() : "未知";

            // 值：null或非数字时默认为0
            Object valueObj = item.get(valueName);
            int value = 0;
            if (valueObj instanceof Number) {
                value = ((Number) valueObj).intValue();
            }

            resultMap.put(key, value);
        }

        return resultMap;
    }
}